from typing import Any, Dict, List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, Path, Body, Request
from sqlalchemy.orm import Session
import json
import asyncio
from datetime import datetime

from database import get_db
from models import Drone, User
from schemas import ResponseModel
from api.deps import get_current_active_user, get_client_ip
from utils import log_operation
# 导入无人机控制服务
from services.Drone_control import drone_controller, DroneCommandError

router = APIRouter()

# 注意：DroneCommand 和 DroneState 枚举已在 Drone_control.py 中定义
# 这里保留以便兼容现有的 get_available_commands 函数
class DroneCommand:
    """无人机命令枚举"""
    TAKEOFF = "takeoff"
    LAND = "land"
    HOVER = "hover"
    MOVE = "move"
    ROTATE = "rotate"
    STOP = "stop"
    SET_SPEED = "set_speed"
    CAMERA_CONTROL = "camera_control"
    DISCONNECT = "disconnect"
    
class DroneState:
    """
    无人机状态枚举
    """
    IDLE = "idle"
    CONNECTED = "connected"
    FLYING = "flying"
    LANDING = "landing"
    ERROR = "error"
    
@router.post("/{drone_id}/connect", response_model=ResponseModel[Dict[str, Any]])
def connect_drone(
    request: Request,
    drone_id: int = Path(..., description="无人机ID"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    连接无人机
    
    建立与无人机的通信连接，准备进行手动控制
    """
    # 验证无人机是否存在
    drone = db.query(Drone).filter(Drone.id == drone_id).first()
    if not drone:
        raise HTTPException(
            status_code=404,
            detail="无人机不存在"
        )
    
    # 只检查电池电量，不检查状态
    if drone.battery_level is not None and drone.battery_level < 20:
        print(f"连接失败: 无人机ID {drone_id} 电池电量过低({drone.battery_level}%)")
        raise HTTPException(
            status_code=400,
            detail=f"无人机电池电量过低({drone.battery_level}%)，无法连接"
        )
    
    try:
        # 使用无人机控制服务连接无人机
        drone_state = drone_controller.connect(
            drone_id=drone_id,
            initial_battery=drone.battery_level or 100
        )
        
        # 更新无人机状态
        drone.status = "busy"
        drone.last_flight_time = datetime.now()
        db.commit()
        
        # 记录操作日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=get_client_ip(request),
            operation_type="connect_drone",
            operation_content=f"用户 {current_user.username} 连接无人机: {drone.name}（ID: {drone_id}）",
            success=1
        )
        
        return ResponseModel(
            data={
                "drone_id": drone_id,
                "drone_name": drone.name,
                "connected": True,
                "message": "无人机连接成功",
                "battery_level": drone_state.battery_level,
                "current_state": drone_state.flight_status
            }
        )
    except DroneCommandError as e:
        raise HTTPException(
            status_code=400,
            detail=str(e)
        )
    except Exception as e:
        print(f"连接无人机失败: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail="连接无人机时发生错误"
        )

@router.post("/{drone_id}/disconnect", response_model=ResponseModel[Dict[str, Any]])
def disconnect_drone(
    request: Request,
    drone_id: int = Path(..., description="无人机ID"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    断开无人机连接
    
    终止与无人机的通信连接
    """
    # 验证无人机是否存在
    drone = db.query(Drone).filter(Drone.id == drone_id).first()
    if not drone:
        raise HTTPException(
            status_code=404,
            detail="无人机不存在"
        )
    
    try:
        # 使用无人机控制服务断开连接
        disconnected = drone_controller.disconnect(drone_id)
        
        # 更新无人机状态为可用
        drone.status = "available"
        db.commit()
        
        # 记录操作日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=get_client_ip(request),
            operation_type="disconnect_drone",
            operation_content=f"用户 {current_user.username} 断开无人机: {drone.name}（ID: {drone_id}）",
            success=1
        )
        
        return ResponseModel(
            data={
                "drone_id": drone_id,
                "disconnected": True,
                "message": "无人机断开连接成功"
            }
        )
    except DroneCommandError as e:
        raise HTTPException(
            status_code=400,
            detail=str(e)
        )
    except Exception as e:
        print(f"断开无人机连接失败: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail="断开无人机连接时发生错误"
        )

@router.get("/{drone_id}/status", response_model=ResponseModel[Dict[str, Any]])
def get_drone_status(
    drone_id: int = Path(..., description="无人机ID"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取无人机状态
    
    返回无人机的详细状态信息，包括连接状态、电池电量、位置等
    """
    # 验证无人机是否存在
    drone = db.query(Drone).filter(Drone.id == drone_id).first()
    if not drone:
        raise HTTPException(
            status_code=404,
            detail="无人机不存在"
        )
    
    try:
        # 使用无人机控制服务获取状态
        drone_state = drone_controller.get_status(drone_id)
        
        # 构建状态信息
        status_info = {
            "drone_id": drone.id,
            "drone_name": drone.name,
            "battery_level": drone_state.battery_level,
            "latitude": drone_state.latitude or drone.latitude,
            "longitude": drone_state.longitude or drone.longitude,
            "altitude": drone_state.altitude or drone.altitude,
            "db_status": drone.status,
            "is_connected": drone_state.connected,
            "connection_info": {"status": drone_state.flight_status} if drone_state.connected else None,
            "flight_status": drone_state.flight_status
        }
        
        # 获取可用命令列表
        status_info["available_commands"] = get_available_commands(drone, status_info)
        
        return ResponseModel(data=status_info)
    except DroneCommandError:
        # 如果无人机不存在于控制器中，返回默认状态
        status_info = {
            "drone_id": drone.id,
            "drone_name": drone.name,
            "battery_level": drone.battery_level,
            "latitude": drone.latitude,
            "longitude": drone.longitude,
            "altitude": drone.altitude,
            "db_status": drone.status,
            "is_connected": False,
            "connection_info": None,
            "flight_status": "idle",
            "available_commands": ["connect"]
        }
        return ResponseModel(data=status_info)
    except Exception as e:
        print(f"获取无人机状态失败: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail="获取无人机状态时发生错误"
        )

@router.post("/{drone_id}/command", response_model=ResponseModel[Dict[str, Any]])
def send_drone_command(
    request: Request,
    drone_id: int = Path(..., description="无人机ID"),
    command: str = Query(..., description="命令类型"),
    params: Optional[Dict[str, Any]] = Body(None, description="命令参数"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    发送控制命令给无人机
    
    根据无人机当前状态，发送相应的控制命令
    """
    # 验证无人机是否存在
    drone = db.query(Drone).filter(Drone.id == drone_id).first()
    if not drone:
        raise HTTPException(
            status_code=404,
            detail="无人机不存在"
        )
    
    # 使用无人机控制服务执行命令
    try:
        result = drone_controller.execute_command(
            drone_id=drone_id,
            command=command,
            params=params or {}
        )
        
        # 更新数据库中的无人机状态（如果需要）
        if result["success"] and command in ["takeoff", "land", "stop"]:
            drone.last_flight_time = datetime.now()
            db.commit()
        
        # 记录操作日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=get_client_ip(request),
            operation_type="send_drone_command",
            operation_content=f"用户 {current_user.username} 向无人机 {drone.name}（ID: {drone_id}）发送命令: {command}，参数: {params}",
            success=1 if result["success"] else 0
        )
        
        return ResponseModel(data=result)
    except DroneCommandError as e:
        raise HTTPException(
            status_code=400,
            detail=str(e)
        )
    except Exception as e:
        print(f"发送命令失败: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail="发送命令时发生错误"
        )

def get_available_commands(drone: Drone, status_info: Dict[str, Any]) -> List[str]:
    """
    根据无人机当前状态，判断可以下发的命令
    
    Args:
        drone: 无人机对象
        status_info: 无人机状态信息
    
    Returns:
        可执行命令列表
    """
    available_commands = []
    
    # 如果未连接，只返回连接命令
    if not status_info.get("is_connected", False):
        return ["connect"]
    
    # 连接状态下的基础命令
    available_commands.append("disconnect")
    
    # 检查电池电量
    battery_level = status_info.get("battery_level", 100)
    if battery_level < 15:
        # 低电量状态下只允许降落和断开连接
        available_commands.append("land")
        return available_commands
    
    # 根据飞行状态判断可用命令
    flight_status = status_info.get("flight_status", DroneState.IDLE)
    
    if flight_status in [DroneState.CONNECTED, DroneState.IDLE]:
        # 地面状态
        available_commands.extend(["takeoff", "hover", "set_speed", "camera_control"])
    
    elif flight_status == DroneState.FLYING:
        # 飞行状态
        available_commands.extend(["land", "hover", "move", "rotate", "stop", "set_speed", "camera_control"])
    
    elif flight_status == DroneState.LANDING:
        # 降落状态
        available_commands.extend(["stop"])
    
    return available_commands

# 注意：execute_drone_command 函数已被 Drone_control.py 中的 drone_controller.execute_command 替代

@router.get("/connections", response_model=ResponseModel[List[Dict[str, Any]]])
def list_connections(
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """
    获取当前所有无人机连接列表
    """
    connections = []
    # 这里可以从drone_controller中获取所有连接的无人机
    # 为了简单起见，我们查询数据库中所有状态为busy的无人机
    busy_drones = db.query(Drone).filter(Drone.status == "busy").all()
    
    for drone in busy_drones:
        try:
            drone_state = drone_controller.get_status(drone.id)
            if drone_state.connected:
                connections.append({
                    "drone_id": drone.id,
                    "drone_name": drone.name,
                    "connected_at": drone.last_flight_time or datetime.now(),
                    "connected_by": current_user.id,  # 简化处理，实际应该记录连接者
                    "status": drone_state.flight_status
                })
        except:
            # 如果获取状态失败，跳过
            continue
    
    return ResponseModel(data=connections)